#include <iostream>
#include <arpa/inet.h>
#include <unistd.h>

#include "wifiDevice.h"
#include "common.h"
#include "readConig.h"

using namespace std;

const int MAXLEN = 1024;	//读取UDP数据报的最大长度

//wifiDevice::wifiDevice(int *ppMap)
wifiDevice::wifiDevice()
{
	//this->ppMap = ppMap;

	Config configSettings("conf");
	listenUDPPort = configSettings.Read("wifiListenPort", 0);
	
	//建立UDP服务器
	listen_sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

	bzero(&local_addr, sizeof(local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	local_addr.sin_port = htons(listenUDPPort);

	Bind(listen_sockfd, (SA *)&local_addr, sizeof(SA));
	cout<<"wifiDevice: UDP server listen on port: "<<listenUDPPort<<endl;

	//建立提交数据的socket
	commit_sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
}

wifiDevice::~wifiDevice()
{
	delete readThread;
	Close(listen_sockfd);
	Close(commit_sockfd);
}

void wifiDevice::startDevice()
{
	readThread = new Thread(this);
	start();				//启动主线程
	sleep(1);
	readThread->start();	//启动设备读线程
}

void wifiDevice::run()
{
	if(Thread::isEquals(readThread))
	{
		cout<<"startWiFiDevice"<<endl;
		int n;
		socklen_t len;
		char mesg[MAXLEN];
		struct sockaddr_in  pcliaddr;
		
		while(true)
		{
			len =  sizeof(SA);
			
			//读取UDP数据报
			bzero(mesg, sizeof(mesg));
			n = Recvfrom(listen_sockfd, mesg, MAXLEN, 0, (SA *)&pcliaddr, &len);

			int programID;
			sscanf(mesg, "%d", &programID);

			//从串口读来的数据中获得程序号，根据程序号读取port号
			//获得port
			int commit_port = ppMap[programID];

			//填写对应进程的端口
			local_addr.sin_port = htons(commit_port);
			
			//计算数据部分的开始位置
			int i;
			for(i = 0; i < n; i++)
			{
				if(mesg[i] == '#')
					break;
			}

			//将数据报透传到上层
			cout<<"wifiDevice: commit to localhost port: "<<commit_port<<endl;
			Sendto(commit_sockfd, mesg + i + 1, n - i - 1, 0, (SA *)&local_addr, sizeof(SA));
		}
	}
}

//发送UDP数据包
int wifiDevice::sendMessage(string remoteAddress, char *buff, int buffSize)
{
	struct sockaddr_in remoteAddr;

	bzero(&remoteAddr, sizeof(remoteAddr));
	remoteAddr.sin_family = AF_INET;
	inet_pton(AF_INET, remoteAddress.c_str(), &(remoteAddr.sin_addr));
	remoteAddr.sin_port = htons(listenUDPPort);

	cout<<"wifiDevice: send to "<<remoteAddress<<" port: "<<listenUDPPort<<" buffSize: "<<buffSize<<endl;
	Sendto(listen_sockfd, buff, buffSize, 0, (SA *)&remoteAddr, sizeof(SA));
}
